/*
 * Copyright (c) 2009-2010 HIT Microelectronic Center
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Jin Yinghan
 *          Wang Shibo
 */

#include "base/intmath.hh"
#include "cpu/edge/pred/perceptron.hh"
#include "cpu/base.hh"

template<class Impl>
PerceptronBP<Impl>::PerceptronBP(DerivEdgeCPUParams *params, bool history)
        :localHistoryTableSize(params->localHistoryTableSize),
         msbHistoryBits(params->msbHistoryBits),
         msbWeightTableSize(params->msbWeightTableSize),
         lsbHistoryBits(params->lsbHistoryBits),
         lsbWeightTableSize(params->lsbWeightTableSize),
         mbHistoryBits(params->mbHistoryBits),
         mbWeightTableSize(params->mbWeightTableSize),
         weightBits(params->weightBits),
         blockShiftAmt(params->blockShiftAmt)
{
    localHistoryPCMask = localHistoryTableSize - 1;

    msbWeightTable.resize(msbWeightTableSize);

    for (unsigned long long i = 0 ; i < msbWeightTableSize ; ++i) {
        WeightTableEntry * msbWeightTableEntry = new WeightTableEntry;
        //(*msbWeightTableEntry).reserve(msbHistoryBits + 1);
        (*msbWeightTableEntry).resize(msbHistoryBits + 1, (int)0);
        msbWeightTable[i] = msbWeightTableEntry;
    }

    msbPCMask = msbWeightTableSize - 1;

    msbHistoryMask = (1<<msbHistoryBits) - 1;
    
    lsbWeightTable.resize(lsbWeightTableSize);

    for (unsigned long long i = 0 ; i < lsbWeightTableSize ; ++i) {
        WeightTableEntry * lsbWeightTableEntry = new WeightTableEntry;
        //(*lsbWeightTableEntry).reserve(lsbHistoryBits + 1);
        (*lsbWeightTableEntry).resize(lsbHistoryBits + 1, (int)0);
        lsbWeightTable[i] = lsbWeightTableEntry;
    }

    lsbPCMask = lsbWeightTableSize - 1;

    lsbHistoryMask = (1<<lsbHistoryBits) - 1;
    
    mbWeightTable.resize(mbWeightTableSize);

    for (unsigned long long i = 0; i < mbWeightTableSize; ++i) {
        WeightTableEntry * mbWeightTableEntry = new WeightTableEntry;
        //(*mbWeightTableEntry).reserve(mbHistoryBits + 1);
        (*mbWeightTableEntry).resize(mbHistoryBits + 1, (int)0);
        mbWeightTable[i] = mbWeightTableEntry;
    }

    mbPCMask = mbWeightTableSize - 1;

    mbHistoryMask = (1<<mbHistoryBits) - 1;

    if (history) {
        historyTable.resize(localHistoryTableSize);

        for (unsigned i = 0 ; i < localHistoryTableSize ; ++i) {
            historyTable[i] = 0;
        }
        
        localFutureFile.resize(Impl::MaxInFlightBlockNum);
    
        for (int i = 0; i < Impl::MaxInFlightBlockNum; ++i) {
            localFutureFile[i].index = 0;
            localFutureFile[i].history = 0;
        }

        historyType = local;
    } else if (!history) {
        historyTable.resize(Impl::MaxThreads);
    
        for (unsigned i = 0; i < Impl::MaxThreads; ++i) {
            historyTable[i] = 0;
        }

        historyFile.resize(Impl::MaxInFlightBlockNum);
    
        for (unsigned i = 0; i < Impl::MaxInFlightBlockNum; ++i) {
            historyFile[i] = 0;
        }

        historyType = global;
    } else {
        fatal("Invalid history type!");
    }

    maxWeight = (1<<(weightBits - 1)) - 1;

    minWeight = -(1<<(weightBits - 1));
} 

template<class Impl>
PerceptronBP<Impl>::~PerceptronBP()
{
    DPRINTF(EdgePerceptron,"Perceptron destructed!\n");
}

template<class Impl>
void
PerceptronBP<Impl>::reset()
{
    for (unsigned long long i = 0 ; i < msbWeightTableSize; ++i) {
        for (unsigned j = 0 ; j <= msbHistoryBits; ++j) {
            (*(msbWeightTable[i]))[j] = 0;
        }
    }
    
    for (unsigned long long i = 0 ; i < lsbWeightTableSize; ++i) {
        for (unsigned j = 0 ; j <= lsbHistoryBits; ++j) {
            (*(lsbWeightTable[i]))[j] = 0;
        }
    }

    for (unsigned long long i = 0 ; i < mbWeightTableSize; ++i) {
        for (unsigned j = 0 ; j <= mbHistoryBits; ++j) {
            (*(mbWeightTable[i]))[j] = 0;
        }
    }

    if (historyType == local) {
        for (unsigned i = 0 ; i < localHistoryTableSize; ++i) {
            historyTable[i] = 0;
        }
            
        for (int i = 0; i < Impl::MaxInFlightBlockNum; ++i) {
            localFutureFile[i].index = 0;
            localFutureFile[i].history = 0;
        }
    } else if (historyType == global) {
        for (unsigned i = 0 ; i < Impl::MaxThreads; ++i) {
            historyTable[i] = 0;
        }
    
        for (unsigned i = 0 ; i < Impl::MaxInFlightBlockNum; ++i) {
            historyFile[i] = 0;
        }
    } else {
        fatal("Invalid history type!");
    }
}

template<class Impl>
TheISA::ExitID
PerceptronBP<Impl>::lookup(BlockID blockID, Addr &block_PC, 
        ThreadID tid)
{
    TheISA::ExitID exitID;

    exitID = lookupExit(block_PC,tid);

    if (historyType == global) {
        speculativeUpdate(tid, blockID, exitID);
    }
    
    return exitID;
}

template<class Impl>
TheISA::ExitID
PerceptronBP<Impl>::update(BlockID blockID, Addr &block_PC, ExitID exitID)
{
    unsigned long long history;
    unsigned long long newHistory;
    unsigned long long localHistoryIdx;
//    bool msb;
//    bool lsb;
//    bool mb;
//    TheISA::ExitID pred_exitID;

    if (historyType == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];
    } else if (historyType == local) {
        localHistoryIdx = block_PC & localHistoryPCMask;
        history = historyTable[localHistoryIdx];
    } else {
        fatal("Invalid history type!");
    }

//    msb = msbPredictorLookup(block_PC, history);

//    lsb = lsbPredictorLookup(block_PC, history);

//    mb = mbPredictorLookup(block_PC, history);

//    pred_exitID = exitGen(msb, lsb, mb);    

    updateMSBWeightTable(blockID, block_PC, exitID);

    updateMBWeightTable(blockID, block_PC, exitID);

    updateLSBWeightTable(blockID, block_PC, exitID);

    if (historyType == local) {
        localHistoryIdx = block_PC & localHistoryPCMask;    
        newHistory = updateHistory(history, exitID);
        historyTable[localHistoryIdx] = newHistory;
    } else if (historyType == global) {
        // Nothing to do
    } else {
        fatal("Invalid history type!");
    }

    DPRINTF(EdgePerceptron,"Perceptron:[bid:%i,PC:%#x], weight updated(exitID: %i).\n",
            blockID,block_PC,exitID); 

//    return pred_exitID;
    return 0xff;
}

template<class Impl>
void
PerceptronBP<Impl>::squash(BlockID blockID, ThreadID tid)
{
    unsigned long long history;

    if (historyType == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];
   
        historyTable[tid] = history;

        DPRINTF(EdgePerceptron,"Perceptron:[bid:%i],squashed.\n", blockID);
    }
}

template<class Impl>
void
PerceptronBP<Impl>::squash(BlockID blockID, ExitID exitID, ThreadID tid)
{
    unsigned long long history;
    if (historyType  == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];

        historyTable[tid] = updateHistory(history, exitID);
    
        DPRINTF(EdgePerceptron,"Perceptron: [bid:%i], squashed due to branch"
            "mispredicted(exitID:%i).\n",blockID,exitID);
    }
}

template<class Impl>
bool
PerceptronBP<Impl>::msbPredictorLookup(Addr &block_PC, unsigned long long history)
{
    unsigned long long msbWeightTableIdx;
    double sum;

    DPRINTF(BPDEBUG, "Lookuping table, history:%#x\n", history);

    msbWeightTableIdx = (block_PC>>blockShiftAmt) & msbPCMask;

    sum =((double) ((*(msbWeightTable[msbWeightTableIdx]))[0]))/0.1111;

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(msbWeightTable[msbWeightTableIdx]))[0]);

    for (unsigned i = 0; i < msbHistoryBits; ++i) {
        if ((history >> i) & 1) {
            sum +=((double)((*(msbWeightTable[msbWeightTableIdx]))[i + 1])) / 
                (0.1111+0.037*((double)(i+1)));

            DPRINTF(BPDEBUG, "weight:%i\n",
                    (*(msbWeightTable[msbWeightTableIdx]))[i + 1]);
        } else {
            sum -= ((double)((*(msbWeightTable[msbWeightTableIdx]))[i + 1])) /
                (0.1111+0.037*((double)(i+1)));

            DPRINTF(BPDEBUG, "weight:%i\n",
                    (*(msbWeightTable[msbWeightTableIdx]))[i + 1]);
        }       
    }
    
    DPRINTF(BPDEBUG,"sum = %.6lf.\n",sum);
    
    if (sum >= 0) {
        return true;
    }

    return false;
}

template<class Impl>
bool
PerceptronBP<Impl>::lsbPredictorLookup(Addr &block_PC, unsigned long long history)
{
    unsigned long long lsbWeightTableIdx;
    double sum;

    DPRINTF(BPDEBUG, "Lookuping table, history:%#x\n", history);

    lsbWeightTableIdx = (block_PC>>blockShiftAmt) & lsbPCMask;

    sum =((double)((*(lsbWeightTable[lsbWeightTableIdx]))[0]))/0.1111;

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(lsbWeightTable[lsbWeightTableIdx]))[0]);

    for (unsigned i = 0 ; i < lsbHistoryBits ; ++i) {
        if ((history >> i) & 1) {
         sum += ((double)((*(lsbWeightTable[lsbWeightTableIdx]))[i + 1])) /
             (0.1111+0.037*((double)(i+1)));

         DPRINTF(BPDEBUG, "weight:%i\n",
                (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]);
        } else {
         sum -= ((double)((*(lsbWeightTable[lsbWeightTableIdx]))[i + 1])) /
             (0.1111+0.037*((double)(i+1)));

         DPRINTF(BPDEBUG, "weight:%i\n",
                (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]);
        }       
    }
    
    DPRINTF(BPDEBUG,"sum = %.6lf.\n",sum);
    
    if (sum >= 0) {
        return true;
    }

    return false;
}

template<class Impl>
bool
PerceptronBP<Impl>::mbPredictorLookup(Addr &block_PC, unsigned long long history)
{
    unsigned long long mbWeightTableIdx;
    double sum;

    DPRINTF(BPDEBUG, "Lookuping table, history:%#x\n", history);
    
    mbWeightTableIdx = (block_PC>>blockShiftAmt) & mbPCMask;

    sum = ((double)((*(mbWeightTable[mbWeightTableIdx]))[0]))/0.1111;

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(mbWeightTable[mbWeightTableIdx]))[0]);

    for (unsigned i = 0 ; i < mbHistoryBits ; ++i) {
        if ((history >> i) & 1) {
            sum += ((double)((*(mbWeightTable[mbWeightTableIdx]))[i + 1])) /
                (0.1111+0.037*((double)(i+1)));

            DPRINTF(BPDEBUG, "weight:%i\n",
                    (*(mbWeightTable[mbWeightTableIdx]))[i + 1]);
        } else {
            sum -= ((double)((*(mbWeightTable[mbWeightTableIdx]))[i + 1])) /
                (0.1111+0.037*((double)(i+1)));

            DPRINTF(BPDEBUG, "weight:%i\n",
                    (*(mbWeightTable[mbWeightTableIdx]))[i + 1]);
        } 
    }

    DPRINTF(BPDEBUG,"sum = %.6lf.\n",sum);

    if (sum >= 0) {
        return true;
    }

    return false;
}

template<class Impl>
void
PerceptronBP<Impl>::updateMSBWeightTable(BlockID blockID, 
        Addr &block_PC, ExitID exitID)
{
    unsigned long long msbWeightTableIdx;
    unsigned long long localHistoryIdx;
    unsigned long long history;
    unsigned exitMSB;

    msbWeightTableIdx = (block_PC>>blockShiftAmt) & msbPCMask;

    if (historyType == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];
    } else if (historyType == local) {
        localHistoryIdx = block_PC & localHistoryPCMask;
        history = historyTable[localHistoryIdx];
    } else {
        fatal("Invalid history type!");
    }

    exitMSB = ((exitID >> 2) & 0x1);

    DPRINTF(BPDEBUG, "Updating table, history:%#x, prediction:%i\n",
            history, exitMSB);

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(msbWeightTable[msbWeightTableIdx]))[0]);

    if (exitMSB == 1) {
        if ((*(msbWeightTable[msbWeightTableIdx]))[0] < maxWeight) {
            (*(msbWeightTable[msbWeightTableIdx]))[0]++;

            DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                    (*(msbWeightTable[msbWeightTableIdx]))[0]);
        }
    } else {
        if ((*(msbWeightTable[msbWeightTableIdx]))[0] > minWeight) {
            (*(msbWeightTable[msbWeightTableIdx]))[0]--;

            DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                    (*(msbWeightTable[msbWeightTableIdx]))[0]);
        }
    }

    for (unsigned i = 0 ; i < msbHistoryBits ; ++i) {

        DPRINTF(BPDEBUG, "weight:%i\n",
                (*(msbWeightTable[msbWeightTableIdx]))[i + 1]);

        if (((history >> i) & 0x1) == exitMSB) {
            if ((*(msbWeightTable[msbWeightTableIdx]))[i + 1] < maxWeight) {
                (*(msbWeightTable[msbWeightTableIdx]))[i + 1]++;

                DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                        (*(msbWeightTable[msbWeightTableIdx]))[i + 1]);
            }    
        } else {
            if ((*(msbWeightTable[msbWeightTableIdx]))[i + 1] > minWeight) {
                (*(msbWeightTable[msbWeightTableIdx]))[i + 1]--;

                DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                        (*(msbWeightTable[msbWeightTableIdx]))[i + 1]);
            }
        }
    }
    
    DPRINTF(EdgePerceptron,"Perceptron[bid:%i,PC:%#x]:msb updated(%i).\n",
            blockID,block_PC,exitMSB);
}

template<class Impl>
void
PerceptronBP<Impl>::updateLSBWeightTable(BlockID blockID, 
        Addr &block_PC, ExitID exitID)
{
    unsigned long long lsbWeightTableIdx;
    unsigned long long localHistoryIdx;
    unsigned long long history;
    unsigned exitLSB;
    
    lsbWeightTableIdx = (block_PC>>blockShiftAmt) & lsbPCMask;

    if (historyType == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];
    } else if (historyType == local) {
        localHistoryIdx = block_PC & localHistoryPCMask;
        history = historyTable[localHistoryIdx];
    } else {
        fatal("Invalid history type!");
    }

    exitLSB = (exitID & 0x1);

    DPRINTF(BPDEBUG, "Updating table, history:%#x, prediction:%i\n",
            history, exitLSB);

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(lsbWeightTable[lsbWeightTableIdx]))[0]);

    if (exitLSB == 1) {
        if ((*(lsbWeightTable[lsbWeightTableIdx]))[0] < maxWeight) {
            (*(lsbWeightTable[lsbWeightTableIdx]))[0]++;

            DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                    (*(lsbWeightTable[lsbWeightTableIdx]))[0]);
        }
    } else {
        if ((*(lsbWeightTable[lsbWeightTableIdx]))[0] > minWeight) {
            (*(lsbWeightTable[lsbWeightTableIdx]))[0]--;

            DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                    (*(lsbWeightTable[lsbWeightTableIdx]))[0]);
        }
    }

    for (unsigned i = 0 ; i < lsbHistoryBits ; ++i) {

        DPRINTF(BPDEBUG, "weight:%i\n",
                (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]);

        if (((history >> i) & 0x1) == exitLSB) {
            if ((*(lsbWeightTable[lsbWeightTableIdx]))[i + 1] < maxWeight) {
                ((*(lsbWeightTable[lsbWeightTableIdx]))[i + 1])++;

                DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                        (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]);
            }    
        } else {
            if ((*(lsbWeightTable[lsbWeightTableIdx]))[i + 1] > minWeight) {
                (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]--;

                DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                        (*(lsbWeightTable[lsbWeightTableIdx]))[i + 1]);
            }
        }
    }

    DPRINTF(EdgePerceptron,"Perceptron[bid:%i,PC:%#x]:lsb updated(%i).\n",
            blockID,block_PC,exitLSB);    
}

template<class Impl>
void
PerceptronBP<Impl>::updateMBWeightTable(BlockID blockID, 
        Addr &block_PC, ExitID exitID)
{
    unsigned long long mbWeightTableIdx;
    unsigned long long localHistoryIdx;
    unsigned long long history;
    unsigned exitMB;

    mbWeightTableIdx = (block_PC>>blockShiftAmt) & mbPCMask;

    DPRINTF(EdgePerceptron,"Perceptron[bid:%i,PC:%#x,mb_idx=%#x]:mb updated(%i).\n",
            blockID,block_PC,mbWeightTableIdx,exitMB);        

    if (historyType == global) {
        history = historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)];
    } else if (historyType == local) {
        localHistoryIdx = block_PC & localHistoryPCMask;
        history = historyTable[localHistoryIdx];
    } else {
        fatal("Invalid history type!");
    }

    exitMB = ((exitID >> 1) & 0x1);

    DPRINTF(BPDEBUG, "Updating table, history:%#x, prediction:%i\n",
            history, exitMB);

    DPRINTF(BPDEBUG, "weight:%i\n",
            (*(mbWeightTable[mbWeightTableIdx]))[0]);

    if (exitMB == 1) {
        if ((*(mbWeightTable[mbWeightTableIdx]))[0] < maxWeight) {
            (*(mbWeightTable[mbWeightTableIdx]))[0] ++;

            DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                    (*(mbWeightTable[mbWeightTableIdx]))[0]);
        }
    } else {
        if ((*(mbWeightTable[mbWeightTableIdx]))[0] > minWeight) {
            (*(mbWeightTable[mbWeightTableIdx]))[0] --;

            DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                    (*(mbWeightTable[mbWeightTableIdx]))[0]);
        }
    }

    for (unsigned i = 0 ; i < mbHistoryBits ; ++i) {

        DPRINTF(BPDEBUG, "weight:%i\n",
                (*(mbWeightTable[mbWeightTableIdx]))[i + 1]);

        if (((history >> i) & 0x1) == exitMB) {
           if ((*(mbWeightTable[mbWeightTableIdx]))[i + 1] < maxWeight) {
               (*(mbWeightTable[mbWeightTableIdx]))[i + 1] ++;

                DPRINTF(BPDEBUG, "Increase the table, get a weight %i\n",
                        (*(mbWeightTable[mbWeightTableIdx]))[i + 1]);
           }
        } else {
           if ((*(mbWeightTable[mbWeightTableIdx]))[i + 1] > minWeight) {
               (*(mbWeightTable[mbWeightTableIdx]))[i + 1] --;

                DPRINTF(BPDEBUG, "Decrease the table, get a weight %i\n",
                        (*(mbWeightTable[mbWeightTableIdx]))[i + 1]);
           }
        }
    }

    DPRINTF(EdgePerceptron,"Perceptron[bid:%i,PC:%#x]:mb updated(%i).\n",
            blockID,block_PC,exitMB);    
}

template<class Impl>
TheISA::ExitID
PerceptronBP<Impl>::exitGen(bool msb, bool lsb, bool mb)
{
    ExitID exitID = 0;
    if (lsb) exitID = exitID | 0x1;
    if (mb) exitID = exitID | 0x2;
    if (msb) exitID = exitID | 0x4;
    return exitID;
}

template<class Impl>
unsigned long long 
PerceptronBP<Impl>::updateHistory(unsigned long long history, TheISA::ExitID exitID)
{
    unsigned long long newHistory;

    newHistory = (history << (exitID + 1)) | 0x1;

    return newHistory;
}

template<class Impl>
TheISA::ExitID
PerceptronBP<Impl>::lookupExit(Addr &block_PC, ThreadID tid)
{
    unsigned long long history;
    unsigned long long localHistoryIdx;
    bool msb;
    bool lsb;
    bool mb;
    TheISA::ExitID exitID;

    if (historyType == global) {

        history = historyTable[tid];

    } else if (historyType == local) {

        localHistoryIdx = block_PC & localHistoryPCMask;
        history = historyTable[localHistoryIdx];

    } else {
        fatal("Invalid history type!");
    }

    msb = msbPredictorLookup(block_PC, history);

    mb = mbPredictorLookup(block_PC, history);

    lsb = lsbPredictorLookup(block_PC, history);

    exitID = exitGen(msb, lsb, mb);

    return exitID;
}

template<class Impl>
void
PerceptronBP<Impl>::speculativeUpdate(ThreadID tid, 
        BlockID blockID,TheISA::ExitID exitID)
{
    unsigned long long history;
    unsigned long long newHistory;

    history = historyTable[tid];

    historyFile[blockID & (Impl::MaxInFlightBlockNum - 1)] = history;
    
    newHistory = updateHistory(history, exitID);

    historyTable[tid] = newHistory;
}

